package com.demo.config.aspect;

import com.demo.common.model.BaseQuery;
import com.demo.common.utils.AuthUtils;
import com.demo.config.annotation.DataScope;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Set;

@Component
@Slf4j
@Aspect
public class DataScopeAspect {
    // 定义切点：匹配
    public static final String POINT_CUT = "@annotation(com.demo.config.annotation.DataScope)";

    @Around(POINT_CUT) // 切入到注解中  前通知：在方法执行前
    public Object before(ProceedingJoinPoint joinPoint) {
        log.info("DataScopeAspect 切面被触发了！");  // 新增这行日志
        Object result = null;
        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        // 获取目标方法
        Method method = methodSignature.getMethod();
        //获取目标方法上指定的注解
        DataScope declaredAnnotation = method.getDeclaredAnnotation(DataScope.class);
        // 获取注解中的属性值
        String tableAlias = declaredAnnotation.tableAlias();
        String tableField = declaredAnnotation.tableField();

        /*
        Tip: 如果用户要是管理员，则没有查询条件，反之只查询用户的信息
         */
        // 查询当前用户的角色列表
        Set<String> roles = AuthUtils.getLoginUserRoles();
        log.info("当前角色为：{}",roles);
        // 判断当前用户是否为管理元角色 "admin"
        if (!roles.contains("admin")){
            // 拼接 SQL 语句片段： where tu.id = #{userId}
            // 获取目标方法中的参数
            Object params = joinPoint.getArgs()[0];
            // 获取当前用户标识
            Integer userId = AuthUtils.getLoginUserId();
            BaseQuery baseQuery = (BaseQuery) params;
            // tableAlias : 表名  tableField：属性名
            baseQuery.setFilterSQL(" and "+tableAlias+"."+tableField+" = "+userId);
        }
        // 执行目标方法
        try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        return result;
    }
}
